/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2018年7月12日
 * V4.0
 */
package com.jphenix.driver.log.xlogc;

//#region 【引用区】
import com.jphenix.share.util.BaseUtil;
import com.jphenix.standard.docs.ClassInfo;

import java.util.ArrayList;
import java.util.List;
//#endregion

//#region 【说明区】
/**
 * 日志信息数据循环存储VO
 * com.jphenix.driver.log.xlogc.LogEventAroundVO
 * 
 * 2024-07-16 修改了获取日志逻辑，效率更高，逻辑更合理
 * 2024-07-30 修改了每次获取日志条目数，降低为50，避免页面卡死
 * 
 * @author MBG
 * 2018年7月12日
 */
//#endregion
@ClassInfo({"2024-07-30 12:30","日志信息数据循环存储VO"})
public class LogEventAroundVO {

	//#region 【声明区】
	private long         pushTime      = 0;                        // 本次放入信息的时间
	private int          elementCount  = 5000;		               // 循环元素个数（信息堆栈深度）
    private int          writePoint    = 0;			               // 元素指针
    private String       serverName    = null;                     // 当前服务器名
    private String       groupName     = null;                     // 当前服务器所属分组名
    private List<String> elementList   = new ArrayList<String>();  // 元素序列           ele:日志内容字符串
    private int          maxReadCount  = 50;                      // 每次读取最大条目数
    //#endregion
    
    //#region setCluster(serverName,groupName) 设置集群信息
	/**
	 * 设置集群信息
	 * @param serverName  当前服务器名
	 * @param groupName   当前服务器所属分组名
	 * 2018年7月17日
	 * @author MBG
	 */
	public void setCluster(String serverName,String groupName) {
		this.serverName = serverName;
		this.groupName  = groupName;
	}
	//#endregion
	
	//#region addLog(content) 添加日志信息
	/**
	 * 添加日志信息
	 * @param content 任务数据字符串
	 * 2016年7月4日
	 * @author MBG
	 */
	public synchronized void addLog(String content) {
		if(elementList.size()>=elementCount) {
			elementList.set(writePoint,content);
		}else {
			elementList.add(writePoint,content);
		}
		writePoint++;
		if(writePoint>=elementCount) {
			writePoint = 0;
		}
	}
	//#endregion
	
	//#region getLog(readPointStr,isLocal) 获取日志
	/**
	 * 获取日志
	 * @param readPointStr  读取日志缓存位置
	 * @param isLocal       是否本机接受获取日志请求（而不是集群中其它服务器发起获取日志请求）
	 * @return              {"readPoint":"读取位置","local":"是否本地日志 0/1","group":"集群分组名","server":"服务器名","logs":["日志条目"]}
	 * 2018年7月17日
	 * @author MBG
	 */
	public String getLog(String readPointStr,boolean isLocal) {
		
		//构建返回值
		StringBuffer reSbf = new StringBuffer();
		
		if(readPointStr==null || readPointStr.length()<1) {
			// 首次读取日志，直接返回写入点信息，并不返回以前的日志
			reSbf.append("{\"readPoint\":").append(writePoint).append(",\"local\":").append(isLocal?"1":"0");
			if(groupName!=null) {
				reSbf
					.append(",\"group\":\"").append(groupName)
					.append("\",\"server\":\"").append(serverName).append("\"");
			}
			return reSbf.append("}").toString();
		}
		// 获取上次读入点位置
		int readPoint = Integer.parseInt(readPointStr);
	    //符合条件的信息序列
		List<String> logList = new ArrayList<String>();
		
		boolean readOver   = false; // 是否读取完毕
		int     readCount  = 0;     // 本次读取条目数
		
		//#region 写入位置在读取位置的前面，说明已经写入一个轮回
		if(readPoint>writePoint) {
			for(int i=readPoint;i<elementList.size();i++) {
				logList.add(elementList.get(i));
				readCount++;
				if(readCount>=maxReadCount) {
					readOver = true;
					break;
				}
			}
			if(!readOver) {
				for(int i=0;i<writePoint;i++) {
					logList.add(elementList.get(i));
					readCount++;
					if(readCount>=maxReadCount) {
						readOver = true;
						break;
					}
				}
			}
		}
		//#endregion
		
		//#region 写入位置比读取位置大
		else {
			for(int i=readPoint;i<writePoint;i++) {
				logList.add(elementList.get(i));
				readCount++;
				if(readCount>=maxReadCount) {
					readOver = true;
					break;
				}
			}
			
		}
		//#endregion
		
		reSbf
		
			.append("{\"readPoint\":").append(readPoint+readCount)
			.append(",\"local\":").append(isLocal?"1":"0");
		if(groupName!=null) {
			reSbf
				.append(",\"group\":\"").append(groupName)
				.append("\",\"server\":\"").append(serverName).append("\"");
		}

		reSbf.append(",\"logs\":[");
		boolean noFirst = false; //是否不是首次循环
		for(String ele:logList) {
			if(noFirst) {
				reSbf.append(",");
			}else {
				noFirst = true;
			}
			reSbf.append("\"").append(BaseUtil.swap(ele,"\n","\\n","\"","\\\"")).append("\"");
		}
		reSbf.append("]}");
		return reSbf.toString();
	}
	//#endregion

	//#region toString()
	/**
	 * 覆盖方法
	 */
	@Override
    public String toString() {
	    //构造返回值
	    StringBuffer reSbf = new StringBuffer();
	    reSbf
	        .append("pushTime:[")
	        .append(pushTime)
	        .append("] writePoint:[")
	        .append(writePoint)
	        .append("] elementCount:[")
	        .append(elementCount)
	        .append("] elementSize:[")
	        .append(elementList.size())
	        .append("]");
	    //不现实详细内容，因为如果元素量过大，会导致输出过多内容
	    return reSbf.toString();
	}
	//#endregion
}









